package cn.dlc.com.config;

import cn.dlc.com.filter.JwtLoginFilter;
import cn.dlc.com.filter.JwtVerifyFilter;
import cn.dlc.com.handler.SystemAuthenticationEntryPoint;
import cn.dlc.com.handler.MyAccessDeniedHandler;
import cn.dlc.com.handler.SystemLogoutSuccessHandler;
import cn.dlc.com.service.SysLoginLogService;
import cn.dlc.com.service.SysUserService;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
 * @author deng
 * @date 2021/6/25 10:25
 **/
@Configuration
@EnableWebSecurity
@MapperScan("cn.dlc.com.mapper")
@EnableGlobalMethodSecurity(securedEnabled=true,prePostEnabled = true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private SysUserService userService;

    @Autowired
    private SysLoginLogService loginLogService;

    @Autowired
    private RsaPropertiesConfig config;

    @Autowired
    private MyAccessDeniedHandler accessDeniedHandler;

    @Autowired
    private SystemAuthenticationEntryPoint entryPoint;


    @Autowired
    private SystemLogoutSuccessHandler logoutSuccessHandler;

    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }

    // 配置springSecurity的相关信息
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        // 释放静态资源，指定拦截规则，指定自定义认证页面，指定退出的配置，csrf配置
        httpSecurity
                // 配置权限
                .authorizeRequests()

                // 对非放行的所有的请求都需要进行验证
                // 可以通过permitAll放行，或者WebSecurity里面的ignoring进行放行。
                .anyRequest()
                .authenticated()

                // .antMatchers("/shop/hello","/shop/order").authenticated();表示这个路径下的东西需要权限验证，也就是要登录
                .and()
                .logout()
                // 注销之后的操作
                .logoutSuccessHandler(logoutSuccessHandler)

                .and()
//                .addFilter(new JwtLoginFilter(super.authenticationManager(), config))
                .addFilter(new JwtLoginFilter(super.authenticationManager(), config, loginLogService))
//                .addFilter(new JwtVerifyFilter(super.authenticationManager(), config))
                .addFilter(new JwtVerifyFilter(super.authenticationManager(), config,loginLogService))
                // 禁用session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().cors()

                .and().csrf().disable();


        // 用户登录之后，当你没有权限访问数据的时候会提示这个。（必须是认证通过才行，）
        // 如果用户没有设置权限，那么不会有这个提示
        httpSecurity
                .exceptionHandling()
                .authenticationEntryPoint(entryPoint)
                .accessDeniedHandler(accessDeniedHandler);

    }

    // 这样可以放行静态文件
    public void configure(WebSecurity web) throws Exception{
        // 这里配置的放行的优先级非常高，
//        web.ignoring().mvcMatchers("/order/findAll");
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.setAllowCredentials(true);

        source.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(source);
    }

    /**
     * 注册这个权限管理的东西
     * @return
     */
    @Bean
    public DefaultWebSecurityExpressionHandler webSecurityExpressionHandler(){
        DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
        handler.setPermissionEvaluator(new CustomPermissionEvaluator());
        return handler;
    }
}
